package com.atguigu.ware.wares.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.to.es.SkuHasStock;
import com.atguigu.common.to.rabbit.OrderToWaresTo;
import com.atguigu.common.utils.R;
import com.atguigu.ware.wares.entity.WmsWareOrderTaskDetailEntity;
import com.atguigu.ware.wares.entity.WmsWareOrderTaskEntity;
import com.atguigu.ware.wares.feign.WareToOrderFeignService;
import com.atguigu.ware.wares.feign.WareToProductFeign;
import com.atguigu.ware.wares.service.WmsWareOrderTaskDetailService;
import com.atguigu.ware.wares.service.WmsWareOrderTaskService;
import com.atguigu.ware.wares.to.OmsOrderEntity;
import com.atguigu.ware.wares.vo.reqVo.OrderToWareTo;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.ware.wares.dao.WmsWareSkuDao;
import com.atguigu.ware.wares.entity.WmsWareSkuEntity;
import com.atguigu.ware.wares.service.WmsWareSkuService;
import org.springframework.transaction.annotation.Transactional;



@Service("wmsWareSkuService")
public class WmsWareSkuServiceImpl extends ServiceImpl<WmsWareSkuDao, WmsWareSkuEntity> implements WmsWareSkuService {
    @Autowired
    private WmsWareSkuDao wmsWareSkuDao;

    @Autowired
    private WareToProductFeign wareToProductFeign;

    @Autowired

    private WmsWareOrderTaskService wmsWareOrderTaskService;
    @Autowired

    private WmsWareOrderTaskDetailService wmsWareOrderTaskDetailService;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    private WareToOrderFeignService wareToOrderFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<WmsWareSkuEntity> page = this.page(
                new Query<WmsWareSkuEntity>().getPage(params),
                new QueryWrapper<WmsWareSkuEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 采购成功后调用此接口完成入库操作
     *
     * @param skuId
     * @param wareId
     * @param skuNum
     */
    public void addWareSkus(Long skuId, Long wareId, Integer skuNum) {
        //根据商品id和仓库id查询是否存在次入库数据
        WmsWareSkuEntity skuEntity = this.baseMapper.selectOne(new QueryWrapper<WmsWareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
        if (skuEntity != null) {
            //更新操作
            wmsWareSkuDao.updateBySkuIdAndWareId(skuId, wareId, skuNum);

        } else {
            //新增数据
            WmsWareSkuEntity en = new WmsWareSkuEntity();
            en.setSkuId(skuId);
            en.setWareId(wareId);
            en.setStock(skuNum);

            //远程调用设置skuName
            //TODO 当远程调用出现异常时现在用的是try让其不回滚，我们可以适用更高级的方法
            try {
                R r = wareToProductFeign.queryByWareInfo(skuId);
                Map<String, Object> map = (Map<String, Object>) r.get("skuInfo");
                if (r.getCode() == 0) {
                    en.setSkuName((String) map.get("skuName"));
                }
            } catch (Exception e) {

            }


            this.save(en);

        }

    }

    /**
     * 分组查询对应的sku是否存在库存
     *
     * @param skuIds
     * @return
     */
    public List<SkuHasStock> skuIdInfo(List<Long> skuIds) {
        List<SkuHasStock> skuHasStocks = this.baseMapper.skuIdInfo(skuIds);
        if (skuHasStocks != null && skuHasStocks.size() > 0) {
            return skuHasStocks;
        }
        return new ArrayList<SkuHasStock>();
    }

    /**
     * 锁定库存业务类书写
     *
     * @param orderToWareTos
     */
    @Transactional
    public Boolean orderLock(List<OrderToWareTo> orderToWareTos) {
        //新增库存工作单
        WmsWareOrderTaskEntity entity = new WmsWareOrderTaskEntity();
        entity.setOrderId(orderToWareTos.get(0).getOrderId());
        entity.setOrderSn(orderToWareTos.get(0).getOrderSn());
        wmsWareOrderTaskService.save(entity);
        boolean flag = true;
        int i = 0;
        for (OrderToWareTo orderToWareTo : orderToWareTos) {
            //获取存在该产品的所有仓库
            Long skuId = orderToWareTo.getSkuId();
            List<WmsWareSkuEntity> wmsWareSkuEntities = this.list(new QueryWrapper<WmsWareSkuEntity>().eq("sku_id", skuId));
            //需要判断在这些仓库中是否可以将我们库存锁定
            if (wmsWareSkuEntities != null && wmsWareSkuEntities.size() > 0) {
                for (WmsWareSkuEntity en : wmsWareSkuEntities) {
                    //我们这里只做简单处理--那个仓库能处理--不看具体的位置
                    int num = en.getStock() - en.getStockLocked();
                    if (num >= orderToWareTo.getNum()) {
                        en.setStockLocked(en.getStockLocked() + orderToWareTo.getNum());
                        this.updateById(en);
                        //将数据新增到库存工作单中
                        insertOrderTaskDetail(orderToWareTo.getSkuId(), orderToWareTo.getNum(), entity.getId(), en.getWareId());
                        //说明可以锁定库存--执行sql
                        break;
                    } else {
                        i++;
                    }

                }
                if (i == wmsWareSkuEntities.size()) {
                    flag = false;
                }
            } else {
                flag = false;
            }

        }
        return flag;
    }

    /**
     * 新增库存工作单
     *
     * @param skuId
     * @param num
     * @param id
     * @param wareId
     */
    public void insertOrderTaskDetail(Long skuId, Integer num, Long id, Long wareId) {
        WmsWareOrderTaskDetailEntity entity = new WmsWareOrderTaskDetailEntity();
        entity.setLockStatus(1);
        entity.setSkuId(skuId);
        entity.setSkuNum(num);
        entity.setTaskId(id);
        entity.setWareId(wareId);
        //新增库存工作单
        wmsWareOrderTaskDetailService.save(entity);
        //保存成功之后发送消息告诉已经将库存锁定成功
        rabbitTemplate.convertAndSend("stock-event-exchange", "stock.locked", entity);
    }

    /**
     * 监听库存解锁方法
     */
    public void unlock(WmsWareOrderTaskDetailEntity entity, Message message, Channel channel) throws IOException {
        //获取库存工作单
        //根据库存工作单查询是否还存在对应主表--如果不存在说明库存存在问题--整体回滚了
        Long taskId = entity.getTaskId();
        //根据id获取主表的订单id
        WmsWareOrderTaskEntity wmsWareOrderTask = wmsWareOrderTaskService.getById(taskId);
        if (wmsWareOrderTask != null) {
            //说明没有回滚--继续下一步-需要根据订单id远程查询对应订单表的状态
            R r = wareToOrderFeignService.info(wmsWareOrderTask.getOrderId());
            if (r.getCode() == 0) {
                //远程调用成功
                OmsOrderEntity omsOrderEntity = r.getData("omsOrder",new TypeReference<OmsOrderEntity>() {
                });
                if (omsOrderEntity == null || omsOrderEntity.getStatus() == 4) {
                    //说明订单出现问题了，回滚了，或者是用户手动取消了
                    //解锁库存--需要手动查询一下对应是否已经解锁了
                    if(omsOrderEntity!=null){
                        boolLocks(omsOrderEntity.getOrderSn());
                    }else {
                        //解锁即可
                        deblocking(entity);
                    }

//
                    //将消息手动确认--不重新入队处理
//                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                }else {
                    //说明订单是正常的无需解锁
//                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                }
            } else {
//                //重新入队
//                channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
                throw new RuntimeException("远程调用失败，将消息重现入队，等待另一个分布式系统处理");

            }


        } else {
            //说明主表已经回滚了--无需解锁
//            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }

    }

    /**
     * 解锁库存--根据订单状态来解锁
     *
     * @param entity
     */
    @Transactional
    public void deblocking(WmsWareOrderTaskDetailEntity entity) {
        wmsWareSkuDao.deblocking(entity);
        //然后修改对应库存工作单的状态变为已解锁
        entity.setLockStatus(2);
        wmsWareOrderTaskDetailService.updateById(entity);


    }

    /**
     * 解锁库存--订单自动触发解锁库存--当用户点击删除订单-用户点击关闭订单--到时间之后我们系统解除订单触发
     *
     * @param entity
     */
    public void orderToWaresTo(OrderToWaresTo entity, Message message, Channel channel) throws IOException {
        System.out.println("按照正常的流程解除库存");
       //根据订单号去查询库存是否已经解锁了，由于网络卡顿可能会存在这种情况
        String orderSn = entity.getOrderSn();
        //查询是否需要解锁--需要解锁才解锁
        boolLocks(orderSn);
//        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

    }

    public void boolLocks(String orderSn) {

        WmsWareOrderTaskEntity order_sn = wmsWareOrderTaskService.getOne(new QueryWrapper<WmsWareOrderTaskEntity>().eq("order_sn", orderSn));
        if(order_sn!=null){
            //查询库存工作单记录
            List<WmsWareOrderTaskDetailEntity> wmsWareOrderTaskDetailEntities = wmsWareOrderTaskDetailService.getBaseMapper().selectList(new QueryWrapper<WmsWareOrderTaskDetailEntity>().eq("task_id", order_sn.getId()));
            if(wmsWareOrderTaskDetailEntities!=null && wmsWareOrderTaskDetailEntities.size()>0){
                for (WmsWareOrderTaskDetailEntity ware : wmsWareOrderTaskDetailEntities) {
                    if(ware.getLockStatus()==1){
                        //需要解锁库存
                        deblocking(ware);
                    }

                }
            }
        }
    }

}